#include "opto_display.hpp"

// Opto C API
#include "OptoDisplay.h"
#include "OptoImage.h"

namespace Opto
{
	//============================================================================
	// Opto::DisplayWindow (13/11/2020)
	// Opto display window class
	// Manage an image display window
	//============================================================================
	DisplayWindow::DisplayWindow() : m_name("")
	{
	}

	DisplayWindow::~DisplayWindow()
	{
	}

	// copy constructor
	DisplayWindow::DisplayWindow(const DisplayWindow& w)
	{
		m_name = w.m_name;
	}

	// assignment operator
	DisplayWindow& DisplayWindow::operator=(const DisplayWindow& w)
	{
		m_name = w.m_name;
		return *this;
	}

	// display management
	void DisplayWindow::create(const std::string& name)
	{
		Opto::Image image;
		image.create(Opto::Image::Type::RGB24, 1, 1);
		int error = OptoDisplay_DisplayImage(image.weakPointer().lock().get(), name.c_str(), std::string("").c_str());
		if(OPTO_FAILED(error))
			throw Exception(error, "Opto::DisplayWindow::create()");
		OptoDisplay_ShowWindow(name.c_str(), false);
		m_name = name;
	}

	void DisplayWindow::close()
	{
		OptoDisplay_ShowWindow(m_name.c_str(), false);
	}

	std::string DisplayWindow::name()
	{
		return m_name;
	}

	void DisplayWindow::displayImage(const Image& image, const std::string& title)
	{
		int error = OptoDisplay_DisplayImage(image.weakPointer().lock().get(), m_name.c_str(), title.c_str());
		if(OPTO_FAILED(error))
			throw Exception(error, "Opto::DisplayWindow::displayImage()");
		OptoDisplay_ShowWindow(m_name.c_str(), true);
	}

	void* DisplayWindow::getWindowHandle()
	{
		void* hWnd = nullptr;
		int error = OptoDisplay_GetWindowHandle(m_name.c_str(), &hWnd);
		if(OPTO_FAILED(error))
			throw Exception(error, "Opto::DisplayWindow::getWindowHandle()");
		return hWnd;
	}

	void DisplayWindow::show(bool visible)
	{
		int error = OptoDisplay_ShowWindow(m_name.c_str(), visible);
		if(OPTO_FAILED(error))
			throw Exception(error, "Opto::DisplayWindow::show()");
	}

	void DisplayWindow::move(Point2d topLeft)
	{
		int error = OptoDisplay_MoveWindow(m_name.c_str(), OptoImage_MakePoint(topLeft.x(), topLeft.y()));
		if(OPTO_FAILED(error))
			throw Exception(error, "Opto::DisplayWindow::move()");
	}


	void DisplayWindow::resize(int width, int height)
	{
		int error = OptoDisplay_ResizeWindow(m_name.c_str(), width, height);
		if(OPTO_FAILED(error))
			throw Exception(error, "Opto::DisplayWindow::resize()");
	}


	void DisplayWindow::setTitle(const std::string& title)
	{
		int error = OptoDisplay_SetWindowTitle(m_name.c_str(), title.c_str());
		if(OPTO_FAILED(error))
			throw Exception(error, "Opto::DisplayWindow::setTitle()");
	}

	int DisplayWindow::waitKey(int timeoutMs)
	{
		return OptoDisplay_WaitKey(timeoutMs);
	}

	
	void DisplayWindow::setRoi(const Opto::Roi& roi)
	{
		int error = OptoDisplay_SetRoi(m_name.c_str(), roi.weakPointer().lock().get());
		if(OPTO_FAILED(error))
			throw Exception(error, "Opto::DisplayWindow::setRoi()");
	}

	Opto::Roi DisplayWindow::getRoi()
	{
		Opto::Roi roi;
		roi.create();
		int error = OptoDisplay_GetRoi(m_name.c_str(), roi.weakPointer().lock().get());
		if(OPTO_FAILED(error))
			throw Exception(error, "Opto::DisplayWindow::getRoi()");
		return roi;
	}

	void DisplayWindow::setZoomToFit()
	{
		OptoDisplay_SetWindowZoomFit(m_name.c_str());
	}


	void DisplayWindow::setSnaphotMode(bool enabled)
	{
		OptoDisplay_SetSnaphotMode(m_name.c_str(), enabled);
	}

	
}; // Opto namespace